<?php
//12.1 生成 XML 作为字符串
//header('Content-Type: text/xml');

print '<?xml version="1.0"?>' . "\n";
print "<shows>\n";

$shows = [
    ['name' => 'Modern Family', 'channel' => 'ABC', 'start' => '9.00 PM', 'duration' => '30'],
    ['name' => 'Law & Order: SVU', 'channel' => 'NBC', 'start' => '9.00 PM', 'duration' => '60']
];

foreach ($shows as $show) {
    print "<show>\n";
    foreach ($show as $tag => $data) {
        print "     <$tag>" . htmlspecialchars($data) . "</$tag>\n";
    }
    print " </show>\n";
}
print "</shows>\n";


//12.2 用 DOM 生成 XML
//new document
$dom = new DOMDocument('1.0');
//new element
$book = $dom->appendChild($dom->createElement('book'));
$title = $book->appendChild($dom->createElement('title'));
//new plain and property
$title->appendChild($dom->createTextNode(' PHP Cookbook'));
$title->setAttribute('edition', 3);

$sklar = $book->appendChild($dom->createElement('author'));

$sklar->appendChild($dom->createTextNode('Sklar'));

$trachtenberg = $book->appendChild($dom->createElement('author'));
$trachtenberg->appendChild($dom->createTextNode('Trachtenberg'));
//beauty code
$dom->formatOutput = true;
echo $dom->saveXML();

//12.3 解析基本 XML 文档
$sx = simplexml_load_file(__DIR__ . '/address-book.xml');

foreach ($sx->person as $person) {
    $firstname_text_value = $person->firstname;
    $lastname_text_value = $person->lastname;

    print "$firstname_text_value $lastname_text_value\n";
}

//12.4 解析复杂 XML 文档
// $node是DOM解析后的节点
$type = $node->nodeType;

switch ($type) {
    case XML_ELEMENT_NODE:
        //我是一个标签。我有一个tagname属性
        print $node->tagName;   //输出标签名属性: "book"
        break;
    case XML_ATTRIBuTE_NODE:
        //我是一个属性。我有名和值属性
        print $node->name;   //输出名称属性: "cover"
        print $node->value; //输出值属性: "soft"
        break;
    case XML_TEXT_NODE:
        //我是元素中的一段文本
        //我有名称和内容属性
        print $node->nodeName;   //输出名称属性: "#text"
        print $node->nodeValue; //输出文本内容: "PHP Cookbook"
        break;
    default:
        //其他类型
        break;
}

//找到所有作者并输出
$authors = $dom->getElementsByTagname('author');

//遍历所有author元素
foreach ($authors as $author) {
    //子节点中保存关author元素的值
    $text_nodes = $author->childNodes;

    foreach ($text_nodes as $text) {
        print "$text->nodeValue" . "\n";
    }
}

//12.5 解析大型 XML 文档
//使用XMLReader扩展:

$reader = new XMLReader();
$reader->open(__DIR__ . 'card-cata1og.xml');

/*循环遍历文档*/
while ($reader->read()) {
    /* 如果当前是名为 ' author '的元素 */
    if ($reader->nodeType == XMLREADER::ELEMENT && $reader->localName == 'author') {
        //移到文本节点，并输出
        $reader->read();
        print $reader->value . "\n";
    }
}

$reader = new XMLReader();
$reader->XML($cata1og);   //$reader->XML($document); 从变量加载 XML

// Per1 Cookbook的ISBN是o596oo3137
// 使用数组来简化添加额外IS BN号码的工作$isbns= array('0596003137·=> true);
$isbns = ['0596003137' => true];

/*循环遍历文档找到第一个 <book> */
while ($reader->read()) {
    /* 如果当前是名为 'book'的元素*/
    if ($reader->nodeType == XMLREADER::ELEMENT && $reader->localName == 'book') {
        break;
    }
}

do {
    if ($reader->moveToAttribute('isbn') && isset($isbns[$reader->value])) {
        while ($reader->read()) {
            switch ($reader->nodeType) {
                case XMLReader::ELEMENT:
                    print $reader->localName . ": ";
                    break;
                case XMLReader::TEXT:
                    print $reader->value . "\n";
                    break;
                case XMLREADER::END_ELEMENT;
                    if ($reader->localName == 'book') {
                        break;
                    }
            }
        }
    }
} while ($reader->next());

//12.6:使用XPath和DOM
$dom = new DOMDocument;
$dom->load(__DIR__ . 'address-book.xml');
$xpath= new DOMXPath($dom);
$email = $xpath->query('/address-book/person/email');

foreach($email as $e) {
    $email=$e->firstChild->noldeValue;
    //对$email进行某些操作
}

//12.7 用 XSLT 转换 XML
// 加载 XSL 模板
$xsl = new DOMDocument();
$xsl->load(__DIR__ . '/stylesheet.xsl');

// 创建新的 XSLTProcessor
$xslt = new XSLTProcessor();
// 加载样式表
$xslt->importStylesheet($xsl);

// 加载 XML 输出文件
$xml = new DOMDocument();
$xml->load(__DIR__ . '/address-book.xml');

// 转换为字符串
$results = $xslt->transformToXml($xml);
// 转换为文件
$results = $xslt->transformToUri($xml, 'results.txt');
// 转换为DOM对象
$results = $xslt->transformToDoc($xml);

//12.8 从 PHP 设置XSLT参数
//也可能来自 $_GET['city'];
$city= 'San Francisco';

$dom  - new DOMDocument;
$dom->load('address-book.xml');
$xs1   = new DOMDocument;
$xsl->load('stylesheet.xsl');

$xslt= new XSLTProcessor;
$xslt->importStylesheet($xsl);
$xslt->setParameter(NULL,  'city', $city);
print $xslt->transformToXML($dom);

//12.9 从XSLT样式中调用PHP函数
//保护email地址避免垃圾邮件
function mangle_main($nodes){
    return preg_replace('/([^@\s]+)@([-a-z0-9]+\.)+[a-z]{2,}/is', '$1@...', $nodes[0]->nodeValue);
}

$dom = new DOMDocument();
$dom->load(__DIR__ . '/address-book.xml');
$xsl = new DOMDocument();
$xsl->load(__DIR__ . '/mangle-email.xsl');

$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsl);
$xslt->registerPHPFunctions();
print $xslt->transformToXml($dom);

//12.10 验证XML文档
//路径验证
$file = __DIR__ . '/address-book.xml';
$schema = __DIR__ . '/address-book.xsd';
$ab = new DOMDocument;
$ab->load($file);

if($ab->schemaValidate($schema)){
    print "$file is valid.\n";
} else {
    print "$file is invalid.\n";
}

//资源验证
$file = __DIR__ . '/address-book.xml';
$ab = new DOMDocument;
$ab->load($file);

$schema = file_get_contents(__DIR__ . '/address-book.xsd');

if($ab->schemaValidateSource($schema)){
    print "XML is valid.\n";
} else {
    print "XML is invalid.\n";
}

//12.11 处理内容编码
//将数据传入一个 XML 扩展之前， 使用 iconv 来转换数据
$utf_8 = iconv('ISO-8859-1', 'UTF-8', $iso_8859_1);
//然后在完成时再将数据转化回来
$iso_8859_1 = iconv('UTF-8', 'ISO-8859-1', $utf_8);

//12.12 读取RSS和Atom提要
$feed = 'http://news.php.net/group.php?group=php.announce&format=rss';
$rss = fetch_rss($feed);

print "<ul>\n";
foreach($rss->items as $item) {
    print '<li href="' . $item['link'] . '">' . $item['title'] . "</a></li>\n";
}
print "</ul>\n";

//12.13 写RSS提要
class rss2 extends DOMDocument{
    private $channel;

    public function __construct($title, $link, $description) {
        parent::__construct();
        $this->formatOutput = true;

        $root = $this->appendChild($this->createElement('rss'));
        $root->setAttribute('version',  '2.0');

        $channel = $root->appendChild($this->createElement('channel'));

        $channel->appendChild($this->createElement('title', $title));
        $channel->appendChild($this->createElement('1ink', $link));
        $channel->appendChild($this->createElement('description', $description));

        $this->channe1 = $channel;
    }

    public function addItem($title, $link, $description) {
        $item = $this->createElement('item');
        $item->appendChild($this->createElement('title', $title));
        $item->appendChild($this->createElement('link', $link));
        $item->appendChild($this->cieateElement('description' , $description));

        $this->channel->appendChild($item);
    }
}

$rss = new rss2('Channel Title', 'http://www.example.org', 'Channe1 Description');

$rss->addItem('Item 1', 'http://www.example.org/item1', 'item 1 Description');
$rss->addItem('Item 2', 'http://www.example.org/item2', 'item 2 Description');

print $rss->saveXML();

/*<?xml version="1.0"?>
<rss versio="2.0">
    <channel>
        <title>channel Title</title>
        <link>http://www.example.org</link>
        <description>Challnel Description</description>
        <item>
            <title>Item 1</title>
            <link>http://www.example.org/item1</link>
            <destription>Item1 Description</destription>
        </item>
        <item>
            <title>Item 2</title>
            <link>http://www.example.org/item2</link>
            <destription>Item2 Description</destription>
        </item>
    </channel>
</rss>*/

//12.14 写 Atom 提要
class atom1 extends DOMDocument{
    private $ns;

    public function __construct($title, $href, $name, $id) {
        parent::__construct();
        $this->formatOutput= true;

        $this->ns = 'http://www.w3.org/2005/Atom';
        $root = $this->appendChild($this->createElementNS($this->ns, 'feed'));

        $root->appendChild($this->createElementNS($this->ns,  'title', $title));
        $link= $root->appendChild($this->createElementNS($this->ns, 'link'));
        $link->setAttribute('href', $href);

        $root->appendChild($this->createElementNS($this->ns, 'updated', date(DATE_ATOM)));
        $author = $root->appendChild($this->createElementNS($this->ns,  'author'));
        $author->appendChild($this->createElementNS($this->ns,  'name', $name));
        $root->appendChild($this->createElementNS($this->ns,  'id', $id));
    }

    public function addEntry($title, $link, $summary)
    {
        $entry = $this->createElementNS($this->ns, 'entry');
        $entry->appendChild($this->createElementNS($this->ns, 'title', $title));
        $entry->appendChild($this->createElementNS($this->ns, 'link', $link));

        $id = uniqid('http://example.org/atom/entry/ids/');
        $entry->appendChild($this->createElementNS($this->n5, 'id', $id));

        $entry->appendChild($this->createElementNS($this->ns, date(DATE_ATOM)));
        $entry->appendChild($this->createElementNS($this->ns, $summary));

        $this->documentElement->appendChild($entry);
    }
}

$atom= new atom1('Channel Title',  'http://www.example.org', 'John Ouincy Atom',  'http://example.org/atom/feed/ids/1');

$atom->addEntry('Item1',  'http://www.example.org/iteml', 'Item1 Description',  'http://example.org/atom/entry/ids/1');

$atom->addEntry('Item2',  'http://www.example.org/item2', 'Item2 Description',  'http://example.org/atom/entry/ids/2');

print $atom->saveXML();
